package com.jkt.rms.commons.utils;

import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;

import com.jkt.rms.commons.configuration.AppContext;

public class ServiceLocator {
	
	private static final Logger LOGGER = Logger.getLogger(ServiceLocator.class);
	private Map<String, Object> serviceCache = new HashMap<String, Object>();	
	private static volatile Object mutex = new Object();
	private static ServiceLocator serviceLocator;
	
	public static ServiceLocator getServiceLocator() {
		if( serviceLocator == null )
		{
			synchronized (mutex) {
				if (serviceLocator == null) {
					serviceLocator = new ServiceLocator(); 
				}
			}	
		}
		return serviceLocator;
	}
	
	@SuppressWarnings("unchecked")
	public <T> T locate(String serviceName) {
		LOGGER.debug("locate: " + serviceName);
		T service = null;
		try{
			ApplicationContext ctx = AppContext.getApplicationContext();
			service = (T)ctx.getBean(serviceName) ;
			LOGGER.debug("locating Bean Success : " + serviceName);
		}
		catch (Exception e){ 
			LOGGER.error("Exception while locating Bean from context: " + e);
		}
		return service;	
	}
	
	@SuppressWarnings("unchecked")
	public <T> T locate(Class<T> serviceInterface) {
		String serviceName = serviceInterface.getSimpleName();
		LOGGER.debug("locate: " + serviceName);
		T service = null;
		try{
			ApplicationContext ctx = AppContext.getApplicationContext();
			service = (T)ctx.getBean(serviceName) ;
			LOGGER.debug("locating Bean Success : " + serviceName);
		}
		catch (Exception e){ 
			LOGGER.error("Exception while locating Bean from context: " + e);
		}
		return service;		
	}

	/*
	 * Used for the purpose of Test classes
	 */
	public void addService(Class serviceInterface, Object service) {
		if (serviceCache.containsKey(serviceInterface.getSimpleName())) {
			serviceCache.remove(service);
		}
		serviceCache.put(serviceInterface.getSimpleName(), service);
	}
	
	
	/*
	 * Used for the purpose of test engine cleanup process.
	 */
	public static void resetServiceLocator() {
		synchronized (mutex) {
			serviceLocator = null;
		}
	}
	
	
	
	protected ServiceLocator() {
	}
}

